package com.example.gfsquadwebviewproject.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.IBinder;
import androidx.annotation.Nullable;
import com.example.gfsquadwebviewproject.data.ConfigData;
import com.example.gfsquadwebviewproject.data.setting.MqttConfigData;
import com.example.gfsquadwebviewproject.presenter.service.mqtt.IEasyMqttCallBack;
import com.example.gfsquadwebviewproject.util.DeviceUtils;
import com.example.gfsquadwebviewproject.util.L;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * Mqtt服务
 * @author zhangshun
 */
public class MyMqttService extends Service {
    private final String TAG = "MyMqttService";
    private boolean canDoConnect = true;

    MqttConfigData mqttConfigData;
    ConfigData configData;

    private MqttAndroidClient client;
    private MqttConnectOptions conOpt;
    DeviceUtils deviceUtils;

    private Context context;
    private String serverUrl = "";
    private String userName = "admin";
    private String passWord = "password";
    private String clientId = "";
    private int timeOut = 10;
    private int keepAliveInterval = 20;
    private boolean retained = false;
    private boolean cleanSession = false;
    private boolean autoReconnect = true;
    private IEasyMqttCallBack starMQTTCallBack;

    @Override
    public void onCreate() {
        super.onCreate();
        L.d(TAG,"onCreate");

        context = getApplicationContext();
        mqttConfigData = new MqttConfigData(context);
        configData = new ConfigData(context);
        deviceUtils = new DeviceUtils(context);

        init();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        L.d(TAG,"onBind");
        return binder;
    }

    // 创建一个内部类的实例，被活动获得后，操作服务
    public mBinder binder = new mBinder();

    // 创建一个内部类，继承自Binder，需要活动操作的函数都定义在这个内部类中
    public class mBinder extends Binder {

        public void stop(){
            StopServiceSocket();
        }

        public void connect(IEasyMqttCallBack iEasyMqttCallBack){
            starMQTTCallBack = iEasyMqttCallBack;
            toConnect();
        }

        public void disconnect(){
            toDisconnect();
        }

        public boolean isConnected(){
            return toIsConnected();
        }

        public void reConnect(IEasyMqttCallBack iEasyMqttCallBack){
            disconnect();
            init();
            starMQTTCallBack = iEasyMqttCallBack;
            toConnect();
        }

        public void subscribe(String[] topics, int[] qos){
            toSubscribe(topics, qos);
        }
    }


    /**
     * 发布消息
     * @param msg
     * @param topic
     * @param qos
     * @param retained
     */
    public void publish(String msg, String topic, int qos, boolean retained) {
        try {
            client.publish(topic, msg.getBytes(), qos, retained);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void init() {
        serverUrl = "tcp://"+mqttConfigData.getMqtt_ip()+":"+mqttConfigData.getMqtt_port();
        userName = "admin";
        passWord = "password";

        clientId = deviceUtils.getMac();
        if (clientId==null || clientId.equals("null")){
            clientId = "";
        }
        L.d(TAG,"clientId:"+clientId);

        timeOut = 10;//
        keepAliveInterval = 20;//心跳包默认的发送间隔
        retained = false;//是否保留
        cleanSession = true;//设置清除回话session  true(false) 不收(收)到服务器之前发出的推送消息
        autoReconnect = true;//设置自动重连

        // 服务器地址（协议+地址+端口号）
        client = new MqttAndroidClient(context, serverUrl, clientId);
        // 设置MQTT监听并且接受消息
        client.setCallback(mqttCallback);

        conOpt = new MqttConnectOptions();
        // 清除缓存
        conOpt.setCleanSession(cleanSession);
        // 设置超时时间，单位：秒
        conOpt.setConnectionTimeout(timeOut);
        // 心跳包发送间隔，单位：秒
        conOpt.setKeepAliveInterval(keepAliveInterval);
        // 用户名
        conOpt.setUserName(userName);
        // 密码
        conOpt.setPassword(passWord.toCharArray());
        conOpt.setAutomaticReconnect(autoReconnect);
    }

    /**
     * 关闭客户端
     */
    public void close() {
        try {
            toDisconnect();
            // 关闭客户端
            client.close();
        } catch (Exception e) {
            L.d(TAG,"close error:"+e.toString());
        }
    }

    /**
     * 连接MQTT服务器
     */
    public void toConnect() {
        if (canDoConnect && !client.isConnected()) {
            try {
                client.connect(conOpt,null, iMqttActionListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 订阅主题
     *
     * @param topics 主题
     * @param qos    策略
     */
    public void toSubscribe(String[] topics, int[] qos) {
        try {
            // 订阅topic话题
            L.d(TAG, "execute subscribe -- qos = " + qos.toString());
            client.subscribe(topics, qos);
        } catch (Exception e) {
            L.d(TAG,e.toString());
        }
    }

    /**
     * 断开连接
     */
    public void toDisconnect(){
        try {
            client.disconnect();
        } catch (Exception e) {
            L.d(TAG,"disconnect error:"+e.toString());
        }
    }

    /**
     * 判断连接是否断开
     */
    public boolean toIsConnected(){
        try {
            return client.isConnected();
        } catch (Exception e) {
            L.d(TAG,e.toString());
        }
        return false;
    }

    /**
     *  MQTT是否连接成功
     */
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            if (starMQTTCallBack != null) {
                starMQTTCallBack.connectSuccess(arg0);
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            if (starMQTTCallBack != null) {
                starMQTTCallBack.connectFailed(arg0, arg1);
            }
        }

    };

    // MQTT监听并且接受消息
    private MqttCallback mqttCallback = new MqttCallback() {
        //接受消息
        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            String msgContent = new String(message.getPayload());
            String detailLog = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();
            L.d(TAG, "messageArrived:" + msgContent);
            if (starMQTTCallBack != null) {
                starMQTTCallBack.messageArrived(topic, msgContent, message.getQos());
            }
        }
        //传送完成
        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {
            if (starMQTTCallBack != null) {
                starMQTTCallBack.deliveryComplete(arg0);
            }
            L.i(TAG, "deliveryComplete");
        }

        @Override
        public void connectionLost(Throwable arg0) {
            if (starMQTTCallBack != null) {
                starMQTTCallBack.connectionLost(arg0);
            }
            // 失去连接，重连
        }
    };

    /**
     * 判断网络是否连接
     */
    private boolean isConnectIsNomarl() {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            L.i(TAG, "MQTT current network name：" + name);
            return true;
        } else {
            L.i(TAG, "MQTT no network");
            return false;
        }
    }

    //
    private void StopServiceSocket(){
        L.d(TAG,"服务关闭");
        stopSelf();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        try{
            close();
            client = null;
            L.d(TAG,"onDestroy");
        }
        catch (Exception e){
            L.d(TAG,"onDestroy error:"+e);
        }
    }


}